#include "defaultpainter.h"
#include "QPainter"
#include "QPixmap"
#include "QPainterPath"

#include "gpu_engine/utils/TimeUtils.h"
#include "gpu_engine/log/Log.h"
#include "gpu_engine/GPUBezierThickLineGenerator.h"

DefaultPainter::DefaultPainter() {}

QImage DefaultPainter::Paint(size_t line, size_t nums) {
    QPainter painter;
    QImage image(drawSize, QImage::Format_RGBA8888);
    painter.begin(&image);


    QBrush brush;
    brush.setStyle(Qt::BrushStyle::SolidPattern);

    QBrush pointBrush;
    pointBrush.setStyle(Qt::BrushStyle::SolidPattern);

    BezierParams bezierParams{};
    bezierParams.lineNums = line;
    bezierParams.bodyPointsNums = nums;
    bezierParams.assPointsNums = 10;
    bezierParams.headPointsNums = 5;

    static GPUBezierThickLineGenerator utils;

    if (!initialized) {
        if (!utils.InitializeGPUPipeline(bezierParams)) {
            Logger() << "Failed to initialize GPU pipeline." << std::endl;
            exit(1);
        }
        initialized = true;
    }

    std::vector<BezierLine> lines{};
    for (uint32_t i = 0; i < bezierParams.lineNums; i++) {
        BezierLine line{
            .points = {
                {.x = 500, .y = 200 + float(i) * 10},
                {.x = 300.0, .y = 100.0},
                {.x = 800.0, .y = 100.0},
                {.x = 900.0, .y = 100.0},
            },
            .beginWidth = 100.0f,
            .endWidth = 10.0f,
        };
        lines.push_back(line);
    }

    const uint64_t now = TimeUtils::GetCurrentMonoMs();
    const Point2D *points = utils.GenerateThickLine(lines);
    const uint64_t last = TimeUtils::GetCurrentMonoMs();

    std::cout << "Totally Usage: " << last - now << " ms" << std::endl;
    const size_t pointsNums = 2 * bezierParams.bodyPointsNums + bezierParams.assPointsNums + bezierParams.headPointsNums;

    for (uint32_t lineIdx = 0; lineIdx < bezierParams.lineNums; lineIdx++) {
        brush.setColor(QColor(rand() % 255, rand() % 255, rand() % 255));
        painter.setBrush(pointBrush);
        QPainterPath path;
        for (uint32_t pointIdx = 0; pointIdx < pointsNums; pointIdx++) {
            const uint32_t offset = lineIdx * pointsNums;
            const auto [x, y] = points[offset + pointIdx];
            if (pointIdx == 0) {
                path.moveTo({x,y});
                painter.drawEllipse(QPointF{x,y}, 3, 3);
            } else {
                path.lineTo({x,y});
                painter.drawEllipse(QPointF{x,y}, 3, 3);
            }
        }
        path.closeSubpath();
        painter.fillPath(path, brush);
    }

    painter.end();
    return image;
}
